package com.charging.business.config;

import com.charging.business.domain.Arfd;
import com.charging.business.vo.obj.SplitProvinceMini;
import lombok.Getter;
import lombok.Setter;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author JerryLu
 * @date 2024/8/16 11:24
 * @description 费率库应用
 */
@Component
public class MinFeeManager {
    private static final MinFeeManager INSTANCE = new MinFeeManager();
    // 用于记录上次更新时间
    private final AtomicReference<LocalDateTime> dtUpdate = new AtomicReference<>(LocalDateTime.MIN);
    // 用于存储费率数据
    public ConcurrentHashMap<String, List<Arfd>> dbMinFee = new ConcurrentHashMap<>();

    /**
     * -- GETTER --
     * 获取当前最小费版本
     *
     * @return java.lang.String
     */
    @Getter
    @Setter
    private String minFeeVersion = "";

    // 提供公共的静态方法来获取实例
    public static MinFeeManager getInstance() {
        return INSTANCE;
    }

    @Async
    public CompletableFuture<Void> updateFeeRatesAsync(String version, Map<String, List<Arfd>> db) {
        return CompletableFuture.runAsync(() -> this.updateFeeRates(version, db));
    }

    public void updateFeeRates(String version, Map<String, List<Arfd>> db) {
        synchronized (MinFeeManager.class) {
//            if (isVersionNewer(version)) {
                minFeeVersion = version;
                dbMinFee.clear();
                dbMinFee.putAll(db);
                dtUpdate.set(LocalDateTime.now());
//            }
        }
    }

    public boolean isVersionNewer(String version) {
        LocalDateTime versionTime = LocalDateTime.parse(version, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        return versionTime.isAfter(dtUpdate.get());
    }

    @Async
    public CompletableFuture<Void> updateFeeVersionAsync(String version) {
        return CompletableFuture.runAsync(() -> this.updateVersion(version));
    }


    public void updateVersion(String version) {
//        synchronized (this) {
//            System.out.println("v:" + version);
//            System.out.println(isVersionNewer(version));
//            if (isVersionNewer(version)) {
                minFeeVersion = version;
//                dtUpdate.set(LocalDateTime.now());
//            }
//        }
    }

    /**
     * 获取当前最小费版本及其更新时间
     *
     * @return java.lang.String
     * @author JerryLu
     * @date 2024/8/16 11:47
     */
    public String getMFeeVerEx() {
        return minFeeVersion + "_" + dtUpdate;
    }

    /**
     * 检查是否需要更新费率数据
     *
     * @param currentVersion 当前版本
     * @return 是否需要更新
     */
    public boolean needsUpdate(String currentVersion) {
        LocalDateTime now = LocalDateTime.now();
        if (minFeeVersion.equals(currentVersion)) {
            return false; // 如果当前版本与缓存中的版本相同，则不需要更新
        }
        return dtUpdate.get().isBefore(now); // 如果上次更新时间早于当前时间，则需要更新
    }

    public List<Arfd> getMinFees(String enStationId, String exStationId, int vehicleType) {
        String key = String.format("%s|%s|%02d", enStationId, exStationId, vehicleType);
        return dbMinFee.get(key);
    }

    public String getCurrentVersion() {
        synchronized (MinFeeManager.class) {
            return minFeeVersion;
        }
    }


    public ArrayList<SplitProvinceMini> getMinFee(boolean bETC, String enStationId, String exStationId, Integer vehicleType) throws Exception {
        synchronized (MinFeeManager.class) {
            ArrayList<SplitProvinceMini> provs = new ArrayList<>();
            String key = String.format("%s|%s|%02d", enStationId, exStationId, vehicleType);
            List<Arfd> list = dbMinFee.get(key);

//            List<Arfd> list = getMinFees(enStationId, exStationId, vehicleType);
            // 如果缓存中没有数据，则从db3文件中读取
            if (list != null) {
                for (Arfd row : list) {
                    SplitProvinceMini res = new SplitProvinceMini();
                    res.provinceId = Integer.parseInt(row.getProv());
                    res.calMinFeeFee = Math.toIntExact(row.getPFee());
                    res.calMinFeeFee95 = Math.toIntExact(row.getPFee95());
                    res.calMinFeeMileage = Math.toIntExact(row.getMilesProv());
                    res.tollIntervalsCount = row.getSGroup().split("\\|").length;
                    res.tollIntervalsGroup = row.getSGroup();
                    res.feeGroup = row.getFeeGroup();
                    res.rateVersion = row.getMVer() + "|" + row.getPVer();

                    /**
                     * todo: 陕西最小费额应收直接获取的tollFee,后续测试通过后优化此处代码
                     */
                    if (bETC) {
                        // 是ETC
                        res.ziMinPayFee = Math.toIntExact(row.getTollFee());
                        res.ziMinFee = Math.toIntExact(row.getTollFee());
                    } else {
                        // 非ETC
                        res.ziMinPayFee = Math.toIntExact(row.getTollFee());
                        res.ziMinFee = Math.toIntExact(row.getTollFee());
                    }
                    provs.add(res);
                }
            }

            return provs;
        }
    }
}
